#include <scos.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <timer.h>

#include "stat.h"

_stats_t background;

void statGet(_stats_t *stats)
{
  char buf[BUFSIZ] = {0};
  FILE *f = fopen("/proc/stat", "r");
  
  if (!f)
  {
    fprintf(stderr, "Couldn't open /proc/stat\n");
    return;
  }
  
  fgets(buf, BUFSIZ, f);
  fclose(f);
  
  sscanf(buf, "%*s %lld %lld %lld %lld %lld %lld %lld",
         &stats->user, &stats->nice, &stats->system, &stats->idle,
         &stats->iowait, &stats->irq, &stats->softirq);
}

stat_t statInit(void)
{
  stat_t _stat;
  
  memset(&_stat, 0, sizeof(stat_t));
  _stat.timer = tmrInit();
  
  return _stat;
}

void statStart(stat_t *_stat)
{
  tmrStart(&_stat->timer);
  statGet(&_stat->start);
}

void statStop(stat_t *_stat)
{
  tmrStop(&_stat->timer);
  statGet(&_stat->stop);
}

double statGetUserInUs(stat_t *_stat)
{
  return (_stat->stop.user-_stat->start.user)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.user;
}

double statGetNiceInUs(stat_t *_stat)
{
  return (_stat->stop.nice-_stat->start.nice)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.nice;
}

double statGetSystemInUs(stat_t *_stat)
{
  return (_stat->stop.system-_stat->start.system)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.system;
}

double statGetIdleInUs(stat_t *_stat)
{
  return (_stat->stop.idle-_stat->start.idle)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.idle;
}

double statGetIOWaitInUs(stat_t *_stat)
{
  return (_stat->stop.iowait-_stat->start.iowait)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.iowait;
}

double statGetIRQInUs(stat_t *_stat)
{
  return (_stat->stop.irq-_stat->start.irq)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.irq;
}

double statGetSoftIRQInUs(stat_t *_stat)
{
  return (_stat->stop.softirq-_stat->start.softirq)/(CLOCKS_PER_SEC/1000000.0) -
         tmrGetValueInUs(&_stat->timer)/1000000.0*background.softirq;
}

LIBCTOR void libstat_init(void)
{
  tmr_t  timer = tmrInit();
  stat_t _stat = statInit();
  double meastime;
  
  memset(&background, 0, sizeof(background));
  
  statStart(&_stat);
  tmrStart(&timer);
  sleep(1);
  statStop(&_stat);
  tmrStop(&timer);
  
  meastime = tmrGetValueInUs(&timer)/1000000.0;
  
  background.user =    statGetUserInUs(&_stat) /    meastime;
  background.nice =    statGetNiceInUs(&_stat) /    meastime;
  background.system =  statGetSystemInUs(&_stat) /  meastime;
  background.idle =    statGetIdleInUs(&_stat) /    meastime;
  background.iowait =  statGetIOWaitInUs(&_stat) /  meastime;
  background.irq =     statGetIRQInUs(&_stat) /     meastime;
  background.softirq = statGetSoftIRQInUs(&_stat) / meastime;  
}
